Common Subexpression Elimination in a Lazy Functional Language

نویسنده

  • Olaf Chitil
چکیده

Common subexpression elimination is a well-known compiler optimisation that saves time by avoiding the repetition of the same computation. To our knowledge it has not yet been applied to lazy functional programming languages, although there are several advantages. First, the referential transparency of these languages makes the identification of common subexpressions very simple. Second, more common subexpressions can be recognised because they can be of arbitrary type whereas standard common subexpression elimination only shares primitive values. However, because lazy functional languages decouple program structure from data space allocation and control flow, analysing its effects and deciding under which conditions the elimination of a common subexpression is beneficial proves to be quite difficult. We developed and implemented the transformation for the language Haskell by extending the Glasgow Haskell compiler and measured its effectiveness on real-world programs. 1 Transformation of Different Language Classes The purpose of common subexpression elimination (CSE) is to reduce the runtime of a program through avoiding the repetition of the same computation. The transformation statically identifies a repeated computation by locating multiple occurrences of the same expression. Repeated computations are eliminated by storing the result of evaluating the expression in a variable and accessing this variable instead of reevaluating the expression. 1.1 Imperative Languages CSE is a well-known standard optimisation which is implemented in most compilers for imperative languages ([ASU86]). The program to be optimised is represented as a flow graph whose nodes are basic blocks, that is sequences of 3-address instructions. An expression on the right hand side of an assignment is a common subexpression if it has been computed before and there is no assignment to any variable of the expression in between. For languages with pointers the latter condition is more complicated. Local elimination of all common subexpressions of a basic block is straightforward. Global elimination requires a data flow analysis, since an expression can only be eliminated, if it is already computed on every path leading to its basic block. It is important to note that some transformations are not feasible on source code level, because the required details are still hidden there. For example Pascal only permits to access an array by an index, e.g. a[i] := a[i]+1. Assuming an array component requires 4 bytes this is translated into the following 3-address code: t1 := 4 * i; t2 := a[t1] t3 := t2 + 1; t4 := 4 * i; a[t4] := t3; The programmer cannot avoid the repeated computation of 4 * i which is eliminated by CSE. Note that 3-address code only handles primitive data like integers and floating point values and that the temporary variables t1, . . . , t4 are held in processor registers. The recomputation of complete arrays for example cannot be eliminated. 1.2 Strict Functional Languages Appel implemented CSE in a compiler for the strict functional language ML ([App92], Chapter 9). He uses continuation passing style as intermediate language on which all transformations operate. Whereas 3-address code consists of a sequence of instructions, continuation passing style code makes control flow explicit by nesting. Hence an expression is evaluated before another expression, if it syntactically dominates that expression. Only in case of syntactic domination common subexpressions can be eliminated. To increase the applicability of the transformation, an additional hoisting transformation is implemented that hoists a continuation expression above another. The following simplified example from ([App92], Chapter 9) shows the transformation of the expression let f c = c (x+y) in f (x+y) k It is written in continuation passing style as FIX([(f, [c], PRIMOP(+, [VAR x, VAR y], [z], [ APP(VAR c, [VAR z])]))], PRIMOP(+, [VAR x, VAR y], [w], [ APP(VAR f, [VAR w, VAR k])])) which is transformed by hoisting into PRIMOP(+, [VAR x, VAR y], [w], [ FIX([(f, [c], PRIMOP(+, [VAR x, VAR y], [z], [ APP(VAR c, [VAR z])]))], APP(VAR f, [VAR w, VAR k]))])

برای دانلود متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

منابع مشابه

Common Subexpressions Are Uncommon in Lazy Functional Languages

Common subexpression elimination is a well-known compiler optimisation that saves time by avoiding the repetition of the same computation. In lazy functional languages, referential transparency renders the identification of common subexpressions very simple. More common subexpressions can be recognised because they can be of arbitrary type whereas standard common subexpression elimination only ...

متن کامل

Correctness of Copy in Calculi with Letrec, Case and Constructors

Call-by-need lambda calculi with letrec provide a rewritingbased operational semantics for (lazy) call-by-name functional languages. These calculi model the sharing behavior during evaluation more closely than let-based calculi that use a fixpoint combinator. In a previous paper we showed that the copy-transformation is correct for the small calculus LRλ. In this paper we demonstrate that the p...

متن کامل

Common Subexpression Elimination in Automated Constraint Modelling

Typically, there are many alternative models of a given problem as a constraint satisfaction problem, and formulating an effective model requires a great deal of expertise. To reduce this bottleneck, automated constraint modelling systems allow the abstract specification of a problem, which can then be refined automatically to a solver-independent modelling language. The final step is to tailor...

متن کامل

MiniZinc with Functions

Functional relations are ubiquitous in combinatorial problems – the Global Constraint Catalog lists 120 functional constraints. This paper argues that the ability to express functional constraints with functional syntax leads to more elegant and readable models, and that it enables a better translation of the models to different underlying solving technologies such as CP, MIP, or SAT. Yet, most...

متن کامل

Generating a Pattern Matching Compiler by Partial Evaluation

Partial evaluation can be used for automatic generation of compilers and was first implemented in [10]. Since partial evaluation was extended to higher order functional languages [9] [2] it has become possible to write denotational semantics definitions of languages and implement these with very few changes in the language treated by partial evaluators. In this paper we use this technique to ge...

متن کامل

ذخیره در منابع من


  با ذخیره ی این منبع در منابع من، دسترسی به آن را برای استفاده های بعدی آسان تر کنید

برای دانلود متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

عنوان ژورنال:

دوره   شماره 

صفحات  -

تاریخ انتشار 1997